package com.facebook.app.client;

import java.util.ArrayList;
import java.util.List;

import com.facebook.app.client.uiElements.HierarchicalTreeModel;
import com.facebook.app.client.uiElements.KMeansTreeModel;
import com.facebook.app.shared.clustering.Centroid;
import com.facebook.app.shared.clustering.Clusterable;
import com.google.gwt.cell.client.Cell;
import com.google.gwt.view.client.SelectionModel;
import com.google.gwt.view.client.TreeViewModel;

public enum ClusteringMethod {
	
	COSINE_HIERARCHICAL_CLUSTERING(ClusteringType.HIERARCHICAL_CLUSTERING) {
		@Override
		public String toString() {
			return "Cosine Similarity"; // TODO (recommended)
		}
	},
	COSINE_K_MEANS(ClusteringType.K_MEANS) {
		@Override
		public String toString() {
			return "Cosine Similarity"; // TODO (recommended)
		}
	},
	SIMPLE_HIERARCHICAL_CLUSTERING(ClusteringType.HIERARCHICAL_CLUSTERING) {
		@Override
		public String toString() {
			return "Simple Similarity";
		}
	},
	SIMPLE_K_MEANS(ClusteringType.K_MEANS) {
		@Override
		public String toString() {
			return "Simple Similarity";
		}
	};
	
	public enum ClusteringType {
		
		HIERARCHICAL_CLUSTERING {
			@Override
			public TreeViewModel display(List<Clusterable> clusterElements, SelectionModel<Clusterable> selectionModel, Cell<Clusterable> cell) {
				
				if (clusterElements.size() > 0) {
					return new HierarchicalTreeModel(clusterElements.get(0), selectionModel, cell);
				} else {
					throw new IllegalArgumentException("clusterElements is empty: " + clusterElements);
				}
			}
			
			@Override
			public String toString() {
				return "Hierarchical Clustering";
			}
		},
		K_MEANS {
			@Override
			public TreeViewModel display(List<Clusterable> clusterElements, SelectionModel<Clusterable> selectionModel, Cell<Clusterable> cell) {
				
				List<Centroid> centroids = new ArrayList<Centroid>(
						clusterElements.size());

				for (Clusterable element : clusterElements) {
					if (element instanceof Centroid) {
						centroids
								.add((Centroid) element);
					}
				}

				return new KMeansTreeModel(centroids, selectionModel, cell);
			}
			
			@Override
			public String toString() {
				return "K-Means";
			}
		};
		
		public abstract TreeViewModel display(List<Clusterable> clusterElements, SelectionModel<Clusterable> selectionModel, Cell<Clusterable> cell);
	}
	
	private final ClusteringType clusteringType;
	
	ClusteringMethod(ClusteringType clusteringType) {
		this.clusteringType = clusteringType;
	}
	
	public ClusteringType getClusteringType() {
		return clusteringType;
	}
	
}
